/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package indexfileprocessor;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import model.FieldList;
import model.Message;

/**
 *
 * @author Zakiy Firdaus
 */
public class IndexFileReader {
    public IndexFileReader(String path) throws IOException {
        File file = new File(path);
        if (!file.exists()) {
            file.createNewFile();
        }
        try {
            //Open the file for both reading and writing
            this.randfile = new RandomAccessFile(file, "r");
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }
    
    /**
     * RandomAccessFile yang digunakan pada kelas ini
     */
    private RandomAccessFile randfile;
    
    /**
     * Fungsi untuk menutup RandomAccessFile randfile yang dibuka oleh konstruktor
     * @throws IOException 
     */
    public void closeRandfile() throws IOException{
        this.randfile.close();
    }
    
    public long getRetrievePosition(String token, long posawal, long posakhir) throws IOException{
        long posisi = (posakhir+posawal)/2;
        String tokenFile = getToken(posisi);
        
        if(posakhir-posawal<10){
            return -1;
        }
        
        if(token.compareToIgnoreCase(tokenFile) > 0){
            return getRetrievePosition(token, posisi, randfile.length());
        } else if(token.compareToIgnoreCase(tokenFile) < 0){
            return getRetrievePosition( token, 0, posisi);
        }
        posisi = randfile.getFilePointer();
        return posisi;
    }
    
    public long getRetrievePosition(String token) throws IOException{
        long posisi = 0;
        String tokenFile = getToken(posisi);
        posisi = randfile.getFilePointer();
        
        if(tokenFile!=null){
            while(token.compareToIgnoreCase(tokenFile) > 0){
                tokenFile = getToken(posisi);
                posisi = randfile.getFilePointer();
                if(tokenFile==null){
                    return -1;
                }
            }
        } else {
            return -1;
        }
            
        if(token.equalsIgnoreCase(tokenFile)){
            return posisi;
        } else {
            return -1;
        }
    }
    
    public String retrieve(int field, long posisi) throws IOException{
        String hasil="";
        randfile.seek(posisi);
        
        String pattern = "@"+field;
        String nextpattern = "@"+(field+1);
        if(field==5){
            nextpattern = "@@";
        }
        String sCurrentLine = randfile.readLine();
        if(sCurrentLine!=null){
            while(!sCurrentLine.equalsIgnoreCase(pattern)){
                sCurrentLine = randfile.readLine();
                if(sCurrentLine==null){
                    break;
                }
            }
        }
        if(sCurrentLine!=null){
            sCurrentLine = randfile.readLine();
            if(sCurrentLine!=null){
                while(!sCurrentLine.equalsIgnoreCase(nextpattern)){
                    hasil += sCurrentLine+"\n";
                    sCurrentLine = randfile.readLine();
                    if(sCurrentLine==null){
                        break;
                    }
                    
                }
            }
        }
        
        return hasil;
    }
    
    /**
     * Fungsi untuk mencari token pada file paling dekat setelah pointer pos
     * @param pos pointer dari randomaccesfile
     * @return string token dari file
     * @throws IOException 
     */
    public String getToken(long pos) throws IOException{
        String hasil="";
        boolean found=false;
        randfile.seek(pos);
        String curr=randfile.readLine();
        while(curr!=null&&!found){
            if(curr.equals("@@")){
                hasil=randfile.readLine();
                found = true;
            } else {
                curr=randfile.readLine();
            }
            
        }
        if(!found){
            hasil = null;
        }
        return hasil;
    }
    
    public String outputString(int field, String token, long pos) throws IOException{
        String hasil="";
        
        FieldList fl = new FieldList(token);
        
        String slistDoc = retrieve(field, pos);
        String[] listDoc = slistDoc.split("\n");
        
        for(String a:listDoc){
            ArrayList<Integer> listpos = new ArrayList<Integer>();
            if(!a.isEmpty()){
                String[] postList = a.split(",");
                for(int i=1;i<postList.length;i++){
                    if(!postList[i].isEmpty()){
                        listpos.add(Integer.parseInt(postList[i]));
                    }
                }
                fl.addPosition(field, Integer.parseInt(postList[0]), listpos);
            }
        }
        
        hasil = fl.toOutputFile(field);
        
        return hasil;
    }
    
    public long half() throws IOException{
        return randfile.length()/2;
    }
    
    public int getDocFreq(long pos) throws IOException{
        int jum = 0;
        randfile.seek(pos);
        String pattern = "@@";
        String sCurrentLine = randfile.readLine();
        if(sCurrentLine!=null){
            while(!sCurrentLine.equalsIgnoreCase(pattern)){
                jum++;
                sCurrentLine = randfile.readLine();
                if(sCurrentLine==null){
                    break;
                }
            }
        }
        
        return jum-5;
    }
    
    public void toOutputFile(int field, String token) throws IOException{
        long pos = getRetrievePosition(token);
        String output = outputString(field, token, pos);
        String namafile = "ZPD-"+Message.getFieldName(field)+"-token.txt";
        
        try {
            // Create file 
            FileWriter fstream = new FileWriter(namafile);
            BufferedWriter out = new BufferedWriter(fstream);
            out.write(output);
            //Close the output stream
            out.close();
        } catch (Exception e) {//Catch exception if any
            System.err.println("Error: " + e.getMessage());
        }
    }
    
    public static void main(String[] args) throws FileNotFoundException, IOException {
        IndexFileReader ifr = new IndexFileReader("body");
        
        long x = ifr.getRetrievePosition("bebek");
        System.out.println("posisi: "+x);
        String hasil = ifr.retrieve(1, x);
        System.out.println("hasil: "+hasil);
        System.out.println("jumlah dok: "+ifr.getDocFreq(x));
        System.out.println("hasil akhir:\n"+ifr.outputString(1, "bebek", x));
        ifr.toOutputFile(1, "bebek");
        
        ifr.closeRandfile();
    }
}
